﻿using Morin.Shared.Common;
using Morin.Shared.Configs;
using Morin.Shared.Models;
using Morin.Storages;

namespace Morin.Services;

public class AppService(IAppStorage appStorage, AppSettingsConfig appSettingsConfig) : IAppService
{
    public void ClassesAddOrUpdate(int id, List<ClassModel> classes)
    {
        appStorage.ClassDict.AddOrUpdate(id, classes, (k, v) => classes);
    }

    public List<ClassModel> GetClasses(int id)
    {
        return appStorage.ClassDict.TryGetValue(id, out var classes) ? classes : [];
    }

    public HistoryViewsModel GetHistoryView(string key)
    {
        return appStorage.HistoryViewDict.TryGetValue(key, out var model) ? model : new HistoryViewsModel();
    }

    public List<HistoryViewsModel> GetHistoryViews(int sourceId, int vodId)
    {
        return appStorage.HistoryViewDict.Values.Where(x => x.VodSourceID == sourceId && x.VodId == vodId).ToList();
    }


    public List<HistoryViewsModel> GetHistoryViews()
    {
        var historyViews = appStorage.HistoryViewDict.Values.ToList();
        if (historyViews.Count != 0) return historyViews;
        historyViews = JsonProvider.FromPathToObjects<HistoryViewsModel>(appSettingsConfig.HistoryViews);
        if (historyViews == null || historyViews.Count == 0) return [];
        foreach (var item in historyViews) HistoryViewsAddOrUpdate(item);

        return historyViews;
    }

    public List<HistoryViewsModel> GetHistoryViews(int sourceId)
    {
        return appStorage.HistoryViewDict.Values.Where(x => x.VodSourceID == sourceId).ToList();
    }


    public List<MediaSourceModel> GetMediaSources()
    {
        var mediaSources = appStorage.MediaSourceDict.Values;
        if (mediaSources.Count != 0) return mediaSources.ToList();
        mediaSources = JsonProvider.FromPathToObjects<MediaSourceModel>(appSettingsConfig.VideoSource);
        if (mediaSources == null || mediaSources.Count == 0) return [];
        foreach (var item in mediaSources) MediaSourcesAddOrUpdate(item);

        return mediaSources.ToList();
    }

    public List<MenuModel> GetMenus()
    {
        return appStorage.Menus;
    }

    public PlaySkipTimeModel GetPlaySkipTime(string key)
    {
        return appStorage.PlaySkipTimeDict.TryGetValue(key, out var playSkipTime)
            ? playSkipTime
            : new PlaySkipTimeModel();
    }

    public List<PlaySkipTimeModel> GetPlaySkipTimes()
    {
        var playSkipTimes = appStorage.PlaySkipTimeDict.Values;
        if (playSkipTimes.Count != 0) return playSkipTimes.ToList();
        playSkipTimes = JsonProvider.FromPathToObjects<PlaySkipTimeModel>(appSettingsConfig.PlaySkipTimes);
        if (playSkipTimes == null || playSkipTimes.Count == 0) return [];
        foreach (var item in playSkipTimes) PlaySkipTimeAddOrUpdate(item);

        return playSkipTimes.ToList();
    }

    public List<PlaySkipTimeModel> GetPlaySkipTimes(int sourceId, int vodId)
    {
        return appStorage.PlaySkipTimeDict.Values.Where(x => x.SourceID == sourceId && x.VodId == vodId).ToList();
    }


    public void HistoryViewsAddOrUpdate(HistoryViewsModel historyView)
    {
        appStorage.HistoryViewDict.AddOrUpdate(historyView.Key, historyView, (k, v) => historyView);
    }

    public void HistoryViewsTryRemove(string key)
    {
        appStorage.HistoryViewDict.TryRemove(key, out _);
    }

    public void LoadHistoryViews()
    {
        var models = JsonProvider.FromPathToObjects<HistoryViewsModel>(appSettingsConfig.HistoryViews);
        if (models == null || models.Count == 0) return;
        foreach (var item in models) HistoryViewsAddOrUpdate(item);
    }

    public void LoadMediaSources()
    {
        var models = JsonProvider.FromPathToObjects<MediaSourceModel>(appSettingsConfig.VideoSource);
        if (models == null || models.Count == 0) return;
        foreach (var item in models) MediaSourcesAddOrUpdate(item);
    }

    public void LoadPlaySkipTimes()
    {
        var models = JsonProvider.FromPathToObjects<PlaySkipTimeModel>(appSettingsConfig.PlaySkipTimes);
        if (models == null || models.Count == 0) return;
        foreach (var item in models) PlaySkipTimeAddOrUpdate(item);
    }

    public VideoSettingsConfig? GetVideoSettings()
    {
        return JsonProvider.FromPathToObject<VideoSettingsConfig>(appSettingsConfig.VideoConfig) ??
               new VideoSettingsConfig();
    }

    public void MediaSourcesAddOrUpdate(MediaSourceModel media)
    {
        appStorage.MediaSourceDict.AddOrUpdate(media.Id, media, (k, v) => media);
    }

    public void MediaSourcesTryRemove(int id)
    {
        appStorage.MediaSourceDict.TryRemove(id, out _);
    }


    public void MenusSave(List<MenuModel> menus)
    {
        appStorage.Menus = menus;
    }

    public void PlaySkipTimeAddOrUpdate(PlaySkipTimeModel skip)
    {
        appStorage.PlaySkipTimeDict.AddOrUpdate(skip.Key, skip, (k, v) => skip);
    }

    public void PlaySkipTimesTryRmove(string key)
    {
        appStorage.PlaySkipTimeDict.TryRemove(key, out _);
    }

    public PlaySkipTimeModel GetPlaySkipTime(int sourceId, int vodId)
    {
        var key = $"{sourceId}|{vodId}";
        return GetPlaySkipTime(key);
    }

    public List<HistorySearchModel> GetHistorySearch()
    {
        var models = appStorage.HistorySearchDict.Values;
        if (models.Count != 0) return models.ToList();
        models = JsonProvider.FromPathToObjects<HistorySearchModel>(appSettingsConfig.HistorySearchs);
        if (models == null || models.Count == 0) return [];
        foreach (var item in models) HistorySearchAddOrUpdate(item);

        return models.ToList();
    }

    public void HistorySearchAddOrUpdate(HistorySearchModel model)
    {
        if (model.KeyWord != null) appStorage.HistorySearchDict.AddOrUpdate(model.KeyWord, model, (k, v) => model);
    }

    public void HistorySearchTryRemove(string key)
    {
        appStorage.HistorySearchDict.TryRemove(key, out _);
    }

    public void LoadHistorySearch()
    {
        var models = JsonProvider.FromPathToObjects<HistorySearchModel>(appSettingsConfig.HistorySearchs);
        if (models == null || models.Count == 0) return;
        foreach (var item in models) HistorySearchAddOrUpdate(item);
    }

    public List<TvSourceModel>? GetTvSources()
    {
        var models = appStorage.TvSources;
        if (models.Count != 0) return models;
        models = JsonProvider.FromPathToObjects<TvSourceModel>(appSettingsConfig.TVSource);
        if (models == null || models.Count == 0) return [];
        TvSourceAddOrUpdate(models);
        return models;
    }

    public void TvSourceAddOrUpdate(TvSourceModel model)
    {
        var index = appStorage.TvSources.IndexOf(model);
        if (index != -1) appStorage.TvSources[index] = model;
        appStorage.TvSources.Add(model);
    }

    public void TvSourceTryRemove(string groupTitle)
    {
        var model = appStorage.TvSources.Find(x => x.GroupTitle != null && x.GroupTitle.Equals(groupTitle));
        if (model != null) appStorage.TvSources.Remove(model);
    }

    public void LoadTvSources()
    {
        var models = JsonProvider.FromPathToObjects<TvSourceModel>(appSettingsConfig.TVSource);
        if (models == null || models.Count == 0) return;
        appStorage.TvSources.Clear();
        TvSourceAddOrUpdate(models);
    }

    public void TvSourceAddOrUpdate(List<TvSourceModel> models)
    {
        appStorage.TvSources.AddRange(models);
    }

    public List<FavoriteModel> GetFavorites()
    {
        var models = appStorage.FavoriteDict.Values;
        if (models.Count != 0) return models.ToList();
        models = JsonProvider.FromPathToObjects<FavoriteModel>(appSettingsConfig.Favorites);
        if (models == null || models.Count == 0) return [];
        FavoriteAddOrUpdate(models.ToList());

        return models.ToList();
    }

    public void FavoriteAddOrUpdate(FavoriteModel model)
    {
        appStorage.FavoriteDict.AddOrUpdate(model.Key, model, (k, v) => model);
    }

    public void FavoriteAddOrUpdate(List<FavoriteModel> models)
    {
        foreach (var item in models) FavoriteAddOrUpdate(item);
    }

    public void FavoriteTryRemove(string key)
    {
        appStorage.FavoriteDict.TryRemove(key, out _);
    }

    public void LoadFavorites()
    {
        var models = JsonProvider.FromPathToObjects<FavoriteModel>(appSettingsConfig.Favorites);
        if (models == null || models.Count == 0) return;
        appStorage.FavoriteDict.Clear();
        FavoriteAddOrUpdate(models);
    }
}